package com.juyu.miliao.api.service;

import com.juyu.miliao.api.domain.Order;
import com.juyu.miliao.api.util.ComputeRedPacketUtil;
import com.juyu.miliao.api.util.Md5Util;
import com.juyu.miliao.api.util.NetUtil;
import com.juyu.miliao.api.util.XmlUtil;
import com.juyu.miliao.common.domain.CommonHead;
import com.juyu.miliao.common.domain.ConfigWxPay;
import com.juyu.miliao.common.util.CommonUtil;
import com.juyu.miliao.common.util.VerifyUtil;
import net.sf.json.JSONObject;
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * @author pengs
 */
@Service
public class WxPayService {
    private final Logger payNotifyLogger = LoggerFactory.getLogger("payNotify");
    @Resource
    private OrderService orderService;
    @Resource
    private ConfigAppService configAppService;
    @Resource
    private PackageOnlineService packageOnlineService;

    @Transactional(rollbackFor = RuntimeException.class)
    public String getWxPay(HttpServletRequest request, String desc,
                           Long userId, int payType, int contentType,
                           Double fee, BigDecimal discountFee, int contentId, String passback_params,
                           ConfigWxPay configWxPay, int robotOrderType, int h5OrderType,int payNum) {
        String temp = "";
        CommonHead com = VerifyUtil.verifyCommonHead(request);
        try {
            Map<String, String> wxMap = new HashMap<String, String>();
            SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmssSSS");
            String nonce_str = ComputeRedPacketUtil.getRandom(100, 999) + sdf.format(new Date());// 随机字符串
            String body = desc;// 商品描述
            String out_trade_no = ComputeRedPacketUtil.getRandom(100, 999) + sdf.format(new Date());
            String feeStr = String.valueOf((fee) * 100);
            String total_fee = feeStr.substring(0, feeStr.indexOf("."));// 总金额 单位为分
            String spbill_create_ip = NetUtil.getIpAddress(request);// 终端IP	// 用户端实际ip
            String trade_type = "APP";// 交易类型 APP
            wxMap.put("appid", configWxPay.getAppid());
            wxMap.put("mch_id", configWxPay.getMchId());
            wxMap.put("nonce_str", nonce_str);
            wxMap.put("body", body);
            wxMap.put("out_trade_no", out_trade_no);
            wxMap.put("total_fee", total_fee + "");
//            wxMap.put("total_fee", String.valueOf(1)); //测试金额
            wxMap.put("spbill_create_ip", spbill_create_ip);
            wxMap.put("notify_url", configWxPay.getNotifyUrl());
            wxMap.put("trade_type", trade_type);
            wxMap.put("attach", passback_params);// 附加数据，在查询API和支付通知中原样返回，该字段主要用于商户携带订单的自定义数据

            String sign = Md5Util.signGFWXPayDataMD5(wxMap, configWxPay.getKey());// 签名
            wxMap.put("sign", sign);
            //微信统一下单
            String url = "https://api.mch.weixin.qq.com/pay/unifiedorder";
            String payXml = XmlUtil.payInfoToXML(wxMap);
            CloseableHttpClient httpclient = HttpClients.createDefault();
            HttpPost httpPost = new HttpPost(url);
            httpPost.setEntity(new StringEntity(payXml, "utf-8"));
            CloseableHttpResponse payResponse = httpclient.execute(httpPost);

            //下订单 返回结果数据
            HttpEntity entity = payResponse.getEntity();
            String result = EntityUtils.toString(entity, "utf-8");
            EntityUtils.consume(entity);
            Map<String, String> resultMap = XmlUtil.parseXml(result);
            String returnCode = resultMap.get("return_code");
            String resultCode = resultMap.get("result_code");
            if ("SUCCESS".equals(returnCode) && "SUCCESS".equals(resultCode)) {
                // 下单成功 初始化订单
                Order order = new Order();
                order.setUserId(userId);
                order.setContentType(contentType);
                order.setFee(fee);
                order.setOrderId(out_trade_no);
                order.setOutId(out_trade_no);
                order.setOrderStatus(2);
                order.setPayType(payType);
                order.setContentId(contentId);
                order.setChannelId(com.getChannel());
                order.setPhoneSystem(CommonUtil.null2Int(com.getPhoneSystem()));
                order.setVersionNum(com.getVersionNum());
                order.setAppPackageId(com.getAppPackageId());
                order.setGroupType(configAppService.getGroupType(com.getAppPackageId(), com.getPhoneSystem()));
                order.setOnline(packageOnlineService.getOnline(com));
                order.setConfigPayId(configWxPay.getId()+"");
                order.setRobotOrderType(robotOrderType);
                order.setH5OrderType(h5OrderType);
                order.setDiscountFee(discountFee);
                order.setPayNum(payNum);
                orderService.insertOrder(order);

                Map<String, String> payMap = new HashMap<String, String>();
                String prepayId = resultMap.get("prepay_id");// 预支付交易会话标识
                // 返回参数 给前端 调起支付
                payMap.put("appid", configWxPay.getAppid()); // 应用id
                payMap.put("partnerid", configWxPay.getMchId()); // 商户号
                payMap.put("prepayid", prepayId); // 预支付交易会话标识
                payMap.put("package", "Sign=WXPay"); // 扩展字段 暂填写固定值Sign=WXPay
                payMap.put("noncestr", ComputeRedPacketUtil.getRandom(100, 999) + sdf.format(new Date())); // 随机字符串
                payMap.put("timestamp", LocalDateTime.now().toEpochSecond(ZoneOffset.of("+8")) + "");// 时间戳10

                sign = Md5Util.signGFWXPayDataMD5(payMap, configWxPay.getKey());
                payMap.put("sign", sign);
                JSONObject jsonObject = JSONObject.fromObject(payMap);
                temp = jsonObject.toString();
            } else {
                if(payNotifyLogger.isErrorEnabled()){
                    payNotifyLogger.error("resultMap={},appId={}",resultMap.toString(),configWxPay.getAppid());
                }

            }
        } catch (Exception e) {
            if(payNotifyLogger.isErrorEnabled()){
                payNotifyLogger.error("微信支付下单异常： ", e);
            }
        }
        return temp;
    }
}